Waht?
Definition
在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
满足设计原则
- 多用组合,少用继承
- 开放-关闭原则,类应该对拓展开放,对修改关闭
Usage
Component是基类。通常是一个抽象类或者一个接口,定义了属性或者方法,方法的实现可以由子类实现或者自己实现。通常不会直接使用该类,而是通过继承该类来实现特定的功能,它约束了整个继承树的行为。比如说,如果Component代表人,即使通过装饰也不会使人变成别的动物。
ConcreteComponent是Component的子类,实现了相应的方法,它充当了“被装饰者”的角色。
Decorator也是Component的子类,它是装饰者共同实现的抽象类(也可以是接口)。比如说,Decorator代表衣服这一类装饰者,那么它的子类应该是T恤、裙子这样的具体的装饰者。
ConcreteDecorator是Decorator的子类,是具体的装饰者,由于它同时也是Component的子类,因此它能方便地拓展Component的状态(比如添加新的方法)。每个装饰者都应该有一个实例变量用以保存某个Component的引用,这也是利用了组合的特性。在持有Component的引用后,由于其自身也是Component的子类,那么,相当于ConcreteDecorator包裹了Component,不但有Component的特性,同时自身也可以有别的特性,也就是所谓的装饰。
Example
人类吃肉方式变化过程:直接吃生肉 -> 煮熟以后再吃 -> 煮熟添加各种配菜和调料再吃 -> …….
1 | /** |
JDK
- Component:InputStream就是装饰者模式中的超类
- ConcreteComponent:ByteArrayInputStream,FileInputStream相当于被装饰者
- Decorator:FilterInputStream
- ConcreteDecorator(继承FilterInputStream):BufferedInputStream,DataInputStream,PushbackInputStream
Code Example1
2
3File file = new File("hello.txt");
FileInputStream in = new FileInputStream(file);
BufferedInputStream inBuffered = new BufferedInputStream(in);
Conclusion
Advantage
使用装饰者模式比使用继承更加灵活,因为它选择通过一种动态的方式来扩展一个对象的功能,在运行时可以选择不同的装饰器,从而实现不同的行为。
通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
具体构件类与具体装饰类可以独立变化,他能是低耦合的。用户可以根据需要来增加新的具体构件类和具体装饰类,在使用时再对其进行各种组合,原有代码无须改变,符合“开闭原则”。
Disadvantage
会产生很多的小对象,增加了系统的复杂性
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
Reference
https://blog.csdn.net/a553181867/article/details/52108423
https://zhuanlan.zhihu.com/p/44003220
设计模式–装饰者模式(在IO体系中的应用):https://blog.csdn.net/u013679744/article/details/77686646